#include <iostream>
#include <fstream>
#include <string>
#include <pthread.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/wait.h>

const int backlog = 5;
const uint16_t Serverport = 8080;
const std::string Serverip = "0.0.0.0";
const char *sep = "\r\n";

#define FILE "./test.html"

enum
{
    SOCKETERR = 1,
    BINDERR,
    LISTENERR
};

int main()
{
    int listensockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (listensockfd < 0)
    {
        std::cerr << "socket create fail..." << std::endl;
        exit(SOCKETERR);
    }

    struct sockaddr_in Server;
    Server.sin_family = AF_INET;
    Server.sin_addr.s_addr = inet_addr(Serverip.c_str());
    Server.sin_port = htons(Serverport);
    socklen_t len = sizeof(Server);

    int n = bind(listensockfd, (const sockaddr *)&Server, len);
    if (n < 0)
    {
        std::cerr << "bind fail..." << std::endl;
        exit(BINDERR);
    }

    if (listen(listensockfd, backlog) < 0)
    {
        std::cerr << "listen fail..." << std::endl;
        exit(LISTENERR);
    }

    while (true)
    {
        struct sockaddr client;
        socklen_t len = sizeof(client);
        int sockfd = accept(listensockfd, (sockaddr *)&client, &len);
        if (sockfd < 0)
        {
            std::cerr << "accept fail.." << std::endl;
            continue;
        }

        std::string inbuffer_stream;
        char buffer[1024];
        // 第四个参数是读取方式
        if (fork() == 0)
        {
            close(listensockfd);
            if (fork() > 0)
                exit(0); // 爸爸进程退出
            // 孙子进程进行工作
            ssize_t s = recv(sockfd, buffer, sizeof(buffer) - 1, 0);
            if (s > 0)
            {
                buffer[s] = 0;
                std::cout << buffer << std::endl;
            }

            // http响应报头 状态行
            // http version 状态码 状态码描述
            // std::string state_line = "http/1.1 307 Temporary Redirect";
            // state_line += sep;
            // // 报头
            // std::string response_line = "content_length：" +  std::to_string(len) + '\n';
            // // std::string response_header = "Location: https://legacy.cplusplus.com/"; //key:value中间的分隔符需要是英文！！！
            // std::string response_header = "Set_Cookie: 2026nxbw"; //key:value中间的分隔符需要是英文！！！

            // response_header += sep;

            // // 空行
            // std::string blank = sep;
            // std::string response = state_line + response_header + blank + file;

            // send(sockfd, response.c_str(), response.size(), 0);
            std::ifstream ifs(FILE);
            if (ifs.is_open())
            {
                ifs.seekg(0, std::ios_base::end);
                size_t len = ifs.tellg();
                ifs.seekg(0, std::ios_base::beg);

                // 将文件数据放到对象中
                char *file = new char[len];
                ifs.read(file, len);

                ifs.close();

                // http响应报头 状态行
                // http version 状态码 状态码描述
                std::string state_line = "http/1.1 200 OK";
                state_line += sep;
                // 报头
                std::string response_line = "content_length: " +  std::to_string(len);
                response_line += sep; 
                // std::string response_header = "Location: https://legacy.cplusplus.com/";
                std::string response_header = "Set-Cookie: 2026nxbw"; // key:value中间的分隔符需要是英文！！！
                response_header += sep;
                // 空行
                std::string blank = sep;
                std::string response = state_line + response_header + blank + file;

                send(sockfd, response.c_str(), response.size(), 0);

                delete[] file;
            }

            exit(0);
        }
        close(sockfd);

        // 等待爷爷进程,也可不等待，托孤给父进程
        waitpid(-1, nullptr, 0);
    }

    return 0;
}

// #include <iostream>
// #include <fstream>
// #include <string>
// #include <cstring>
// #include <unistd.h>
// #include <sys/wait.h>
// #include <sys/socket.h>
// #include <sys/types.h>
// #include <netinet/in.h>
// #include <arpa/inet.h>
// using namespace std;

// int main()
// {
// 	//创建套接字
// 	int listen_sock = socket(AF_INET, SOCK_STREAM, 0);
// 	if (listen_sock < 0){
// 		cerr << "socket error!" << endl;
// 		return 1;
// 	}
// 	//绑定
// 	struct sockaddr_in local;
// 	memset(&local, 0, sizeof(local));
// 	local.sin_family = AF_INET;
// 	local.sin_port = htons(8081);
// 	local.sin_addr.s_addr = htonl(INADDR_ANY);
// 	if (bind(listen_sock, (struct sockaddr*)&local, sizeof(local)) < 0){
// 		cerr << "bind error!" << endl;
// 		return 2;
// 	}
// 	//监听
// 	if (listen(listen_sock, 5) < 0){
// 		cerr << "listen error!" << endl;
// 		return 3;
// 	}
// 	//启动服务器
// 	struct sockaddr peer;
// 	memset(&peer, 0, sizeof(peer));
// 	socklen_t len = sizeof(peer);
// 	for (;;){
// 		int sock = accept(listen_sock, (struct sockaddr*)&peer, &len);
// 		if (sock < 0){
// 			cerr << "accept error!" << endl;
// 			continue;
// 		}
// 		if (fork() == 0){ //爸爸进程
// 			close(listen_sock);
// 			if (fork() > 0){ //爸爸进程
// 				exit(0);
// 			}
// 			//孙子进程
// 			char buffer[1024];
// 			recv(sock, buffer, sizeof(buffer), 0); //读取HTTP请求
// 			cout << "--------------------------http request begin--------------------------" << endl;
// 			cout << buffer << endl;
// 			cout << "---------------------------http request end---------------------------" << endl;

// 			close(sock);
// 			exit(0);
// 		}
// 		//爷爷进程
// 		close(sock);
// 		waitpid(-1, nullptr, 0); //等待爸爸进程
// 	}
// 	return 0;
// }

// void* Routine(void* args)
// {
//     pthread_detach(pthread_self());

//     while(true)
//     {
//         recv(sockfd, );

//     }

//     pthread_exit((void*)666);
// }

// int main()
// {
//     int listensockfd = socket(AF_INET, SOCK_STREAM, 0);
//     if (listensockfd < 0)
//     {
//         std::cerr << "socket create fail..." << std::endl;
//         exit(SOCKETERR);
//     }

//     struct sockaddr_in Server;
//     Server.sin_family = AF_INET;
//     Server.sin_addr.s_addr = inet_addr(Serverip.c_str());
//     Server.sin_port = htons(Serverport);
//     socklen_t len = sizeof(Server);

//     int n = bind(listensockfd, (const sockaddr *)&Server, len);
//     if (n < 0)
//     {
//         std::cerr << "bind fail..." << std::endl;
//         exit(BINDERR);
//     }

//     if (listen(listensockfd, backlog) < 0)
//     {
//         std::cerr << "listen fail..." << std::endl;
//         exit(LISTENERR);
//     }

//     while (true)
//     {
//         struct sockaddr client;
//         socklen_t len = sizeof(client);
//         int sockfd = accept(listensockfd, (sockaddr *)&client, &len);
//         if (sockfd < 0)
//             continue;

//         pthread_t pid;
//         pthread_create(&pid, nullptr, Routine, nullptr);
//     }

//     return 0;
// }